上一篇已經完成了 JWT 的部分功能
接著開始完善 JWT 功能
完成後的資料夾結構如下
schema.resolvers.go
實現 CreateUser funciotn
func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (string, error) {
var user users.User
user.Username = input.Username
user.Password = input.Password
user.Create()
token, err := jwt.GenerateToken(user.Username)
if err != nil{
return "", err
}
return token, nil
}
$ go run server.go
測試一下 CreateUser 能不能成功
打開 http://localhost:8080/
輸入
mutation {
createUser(input: {username: "user1", password: "123"})
}
接著會得到一串 JWT string
{
"data": {
"createUser": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2ODM2MjU1ODcsInVzZXJuYW1lIjoidXNlcjEifQ.FUO8LH8G_FioVmVVMqVhQiqEndmbK_QIdq5KlHFWtwY"
}
}
這階段開始實作當輸入了正確的帳號密碼,就會產生 JWT Token 給 userinternal/users/users.go
實作 Authenticate function
不過要注意一下...這段 Query 是練習做實驗才用的,不然這樣是有暴露密碼的危險性
func (user *User) Authenticate() bool {
statement, err := mig.Db.Prepare("select Password from Users WHERE Username = ?")
if err != nil {
log.Fatal(err)
}
row := statement.QueryRow(user.Username)
var hashedPassword string
err = row.Scan(&hashedPassword)
if err != nil {
if err == sql.ErrNoRows {
return false
} else {
log.Fatal(err)
}
}
return CheckPasswordHash(user.Password, hashedPassword)
}
schema.resolvers.go
實作 Login function
func (r *mutationResolver) Login(ctx context.Context, input model.Login) (string, error) {
var user users.User
user.Username = input.Username
user.Password = input.Password
correct := user.Authenticate()
if !correct {
// 1
return "", &users.WrongUsernameOrPasswordError{}
}
token, err := jwt.GenerateToken(user.Username)
if err != nil{
return "", err
}
return token, nil
}
internal/users/errors.go
處理錯誤回傳
package users
type WrongUsernameOrPasswordError struct{}
func (m *WrongUsernameOrPasswordError) Error() string {
return "wrong username or password"
}
schema.resolvers.go
處理 Refresh Token
func (r *mutationResolver) RefreshToken(ctx context.Context, input model.RefreshTokenInput) (string, error) {
username, err := jwt.ParseToken(input.Token)
if err != nil {
return "", fmt.Errorf("access denied")
}
token, err := jwt.GenerateToken(username)
if err != nil {
return "", err
}
return token, nil
}